#include "tParser.h"
#include "astNodeBase.h"
#include <fstream>
#include <iostream>

using namespace std;

tParser::tParser(void)
{
}


tParser::~tParser(void)
{
}

// No exception are made. It's because I made an assumption
// that no errors would be produced by Java side.
bool tParser::buildAST()
{
	ifstream ifile;
	ifile.open(path);
	string next = "";
	int state = 0;
	int level_current = 0;
	int level_last = -1;
	astNodeBase* currentNode = NULL;
	astNodeBase* lastNode = NULL;
	ignoreList ignore;
	while(true)
	{
		//input and check validity
		ifile >> next;
		if(!ifile) break;
		
		switch(state)
		{
		case 0: //at the beginning, calculate the layer of the AST object
			if(next == "@") level_current++;
			else
			{
				if(ignore.isIn(next))
				{
					state = 2; continue;
				}
				if(level_current > level_last)
				{
					//this is a children node. it must be last node's child or error happens
					currentNode = new astNodeBase;
					currentNode->parent = lastNode;
					currentNode->type = next;
					if(level_last>=0) lastNode->children.push_back(currentNode);
					if(level_current == 0) root = currentNode;
				}
				else if(level_current == level_last)
				{
					//this is the same-level node.
					currentNode = new astNodeBase;
					currentNode->parent = lastNode->parent;
					currentNode->type = next;
					currentNode->parent->children.push_back(currentNode);
				}
				else if(level_current < level_last)
				{
					//should look back a few level.
					//it will never look back to zero level, at least one.
					for(int i = 0; i < level_last - level_current + 1; i++)
					{
						lastNode = lastNode->parent;
					}
					currentNode = new astNodeBase;
					currentNode->parent = lastNode;
					currentNode->type = next;
					currentNode->parent->children.push_back(currentNode);
				}
				state = 1;
				cout<<"level is "<<level_current<<endl;
				cout<<"AST object is "<<next<<endl;
				//should create a node.
				//clean up
				lastNode = currentNode;
				level_last = level_current;
			}
			break;
		case 1: //set the name of the AST object
			{
				if(next != "__nothing__")
				{
					currentNode->name = next;
					//do some other things
					level_current = 0;
					state = 0;
				}
				else //it is nothing.
				{
					state = 0;
					level_current = 0;
				}
			}
			break;
		case 2: //in ignore list, skip next token
			cout<<"Token was ignored.\n";
			state = 0;
			level_current = 0;
			break;
		}

	}
	return false;
}
